home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Meeting Pearls 4
/
Meeting Pearls Vol. IV (1996)(GTI - Schatztruhe)[!].iso
/
Pearls
/
etech
/
GALer20
/
Source
/
GALer
/
Port.asm
< prev
next >
Wrap
Assembly Source File
|
1996-04-05
|
49KB
|
1,667 lines
*
* This file is the interface between the software
* and the hardware of GALer. The routines of this file
* control the hardware.
*
* needed C-compiler optines: register parameter, 32 bit integer
*
* used assembler: asm of SAS/C 6.51
*
* assemble: asm Port.asm
*
* assumed scratch registers of the compiler: D0, D1, A0, A1
INCLUDE "hardware/cia.i"
GAL16V8 EQU 1 ; type of GAL
GAL20V8 EQU 2
GAL22V10 EQU 3
GAL20RA10 EQU 4
IC1 EQU 3 ; number of IC
IC2 EQU 11 ; IC2 only for elektor
IC3 EQU 0 ; IC1-4 : write only
IC4 EQU 1
IC5 EQU 2
IC6a EQU 0 ; IC6, IC7: read only
IC6c EQU 4
IC7 EQU 1
HW_GALER_1_0 EQU 1 ; Hardware-Version
HW_GALER_1_2 EQU 2
HW_GALER_1_3 EQU 3
HW_ELEKTOR_II EQU 10
ON EQU 1 ; for control of the LED
OFF EQU 0
PROG EQU 1 ; Edit-Mode of GAL
VERIFY EQU 0
LOW EQU 0 ; level
HIGH EQU 1
ciab EQU $BFD000
ciaaprb EQU $BFE101
ciaaddrb EQU $BFE301
ciabpra EQU $BFD000
ciabddra EQU $BFD200
SECTION code,CODE
XDEF @InitParPort ; initialize parallel port
XDEF @RestoreParPort ; restore parallel-port
XDEF @InitHardware ; initialize GAL programmer
XDEF @WriteByte ; write byte in shift register
XDEF @ReadByte ; read byte out of shift register
XDEF @SetGAL ; set type of GAL
XDEF @VeditOn ; edit voltage on
XDEF @VeditOff ; disable edit off
XDEF @LED ; control LED
XDEF @EnableVcc ; switch +5V on
XDEF @DisableVcc ; switch +5V off
XDEF @EnableVEdit ; enable edit voltage
XDEF @DisableVEdit ; disable edit voltage
XDEF @EnableOutput ; Ausgangs-Treiber aktivieren
XDEF @DisableOutput ; Ausgangs-Treiber deaktiviern
XDEF @SetRow ; set address at RAG0-RAG5
XDEF @SDIn ; set level of SDIn input
XDEF @SDOut ; get level at SDOut output
XDEF @Clock ; clock impuls at SCLK input
XDEF @STRImpuls ; make STR impuls
XDEF @EditMode ; set bits for edit mode
XDEF @ExitEditMode ; exit edit mode and switch off +5V
XDEF @SetPV ; set PV (VERIFY or PROG)
XDEF @SetVolt ; set voltage for edit mode
XDEF @SetPESSAVE ; set level of PESSAVE pin
XDEF @SetERASE ; set level of ERASE pin
XDEF @SetCLR ; set level of CLR pin
XDEF @SetARCH ; set level of ARCH pin
XDEF @SetBE ; set level of BE pin
XDEF @SetANDBE ; set level of ANDBE pin
XDEF @PollDelay ; wait some micro seconds
XDEF _cia_timer_low
XDEF _cia_timer_high
XDEF _cia_timer_cr
XDEF _cia_timer_start
XDEF _cia_timer_stop
XDEF _hw_version
XREF _GALType
XREF _outIC1
XREF _outIC2
XREF _outIC3
XREF _outIC4
XREF _outIC5
XREF @WaitForTimer
XREF _LVOForbid
XREF _LVOPermit
XREF _prog_volt
* initialize parallel port
@InitParPort:
move.b ciaaddrb,cia_addrb ; save direction of CIAs
move.b ciabddra,cia_bddra
move.b #%11111111,ciaaddrb ; data as output
and.b #%11111010,ciabddra ; use BUSY as input
; use SEL as input (for elektor`s
rts ; hardware)
* restore state of parallel port
@RestoreParPort:
move.b cia_addrb,ciaaddrb ; Restore data direction of CIAs
; but don't restore the state of
move.b cia_bddra,d0 ; the outputs. Otherwise GALer could
and.b #%11111010,ciabddra ; get a command like Vcc or VEdit on.
and.b #%00000101,d0
or.b d0,ciabddra
rts
* initialize hardware: switch all outputs low
* Parameter: none
@InitHardware:
cmp.l #HW_ELEKTOR_II,_hw_version ; which hardware version?
bne.s ih_galer_hw
; elektor hardware
moveq #IC1,d1
moveq #0,d0
bsr @WriteByte
moveq #IC2,d1
moveq #0,d0
bsr @WriteByte
moveq #IC4,d1
moveq #0,d0
bsr @WriteByte
bra.s ih_end
; GALer hardware
ih_galer_hw:
or.b #%00001000,ciaaprb ; PD3=H: Decoder deaktivieren!
and.b #%00001000,ciaaprb ; alle anderen Datenleitungen auf LOW
; ACHTUNG!!!: PD3 darf nur auf LOW-Pegel gehen
; (Decoder aktiviert werden), wenn durch PD0 und
; PD1 das IC, das angesprochen werden soll, bereits
; selektiert ist. Ansonsten bekommt ein IC einen Takt-
; impuls und beim nächsten Strobe liegen dann die
; falschen Daten an.
moveq #IC1,d1
moveq #0,d0
bsr @WriteByte ; Ausgänge von IC1 auf LOW
moveq #IC3,d1
moveq #0,d0
bsr @WriteByte ; Ausgänge von IC3 auf LOW
moveq #IC4,d1
moveq #0,d0
bsr @WriteByte ; Ausgänge von IC4 auf LOW
moveq #IC5,d1
moveq #0,d0
bsr @WriteByte ; Ausgänge von IC5 auf LOW
ih_end: rts
* WriteByte:
* write a byte "byte" into the IC "IC"
* IC can be: GALer: IC = IC1, IC3, IC4, IC5
* Elektor: IC = IC1, IC2, IC4
* MSB is transfered first
* call: WriteByte(byte, IC)
@WriteByte:
movem.l d2/d3,-(sp) ; save register
; d0: data byte
; d1: IC
cmp.l #IC1,d1 ; save values which are to
bne.s wb_1 ; be written into the ICs
move.l d0,_outIC1
bra.s wb_c
wb_1 cmp.l #IC2,d1
bne.s wb_2
move.l d0,_outIC2
bra.s wb_c
wb_2 cmp.l #IC3,d1
bne.s wb_3
move.l d0,_outIC3
bra.s wb_c
wb_3 cmp.l #IC4,d1
bne.s wb_4
move.l d0,_outIC4
bra.s wb_c
wb_4 move.l d0,_outIC5
wb_c
cmp.l #HW_ELEKTOR_II,_hw_version ; which hardware is connected?
bne.s wb_galer_hw
;*** elektor hardware ***
; loading a shift register runs like this:
; 1. store all 24 bit in a CPU-register
; 2. shift them into the shift registers
; 3. set STR of the shift register low to
; load them
and.b #%11110111,ciaaprb ; set STR of the shift registers low
move.l _outIC2,d2 ; store the data of all shift
rol.l #8,d2 ; registers in d2
move.l _outIC1,d3
move.b d3,d2
rol.l #8,d2
move.l _outIC4,d3
move.b d3,d2
rol.l #8,d2
moveq #3*8-1,d3 ; loop counter: number of shift
; registers 3; size 8 bit
wb_l1: rol.l #1,d2 ; get MSB to bit 0
move.b d2,d0
and.b #%00000001,d0 ; get this bit in d0
and.b #%11111110,ciaaprb ; clear D0 of parallel port
or.b d0,ciaaprb ; set D0 according to this bit
or.b #%00000010,ciaaprb ; set CLK low
nop ; wait a little
nop
nop
and.b #%11111101,ciaaprb ; set CLK high
dbf d3,wb_l1 ; shift 24 bits
or.b #%00001000,ciaaprb ; set STR of the shift registers high
bra.s wb_end
wb_galer_hw: ;*** GALer hardware ***
and.b #%11111100,ciaaprb ; PD0 und PD1 setzen (IC aus-
or.b d1,ciaaprb ; wählen)
and.b #%11110111,ciaaprb ; Decoder aktivieren
moveq #7,d3 ; Schleifenzähler
ror.b #3,d0 ; MSB nach D4 (Datenleitung)
wb_l move.b d0,d2 ; Datenbyte sichern
and.b #%00010000,d2 ; Datenbit ausmaskieren
or.b d2,ciaaprb ; Datenbit (PD4) vom Par.-Port setzen
or.b #%00001000,ciaaprb ; Clock-Impuls durch PD3 geben
and.b #%11110111,ciaaprb ; LOW-HIGH Übergang
and.b #%11101111,ciaaprb ; Datenbit (PD4) auf LOW
rol.b #1,d0 ; nächstniedrigeres Bit senden
dbf d3,wb_l
or.b #%00001000,ciaaprb ; Decoder wieder deaktivieren!!!
; (sehr WICHTIG, siehe InitHardware)
or.b #%00000100,ciaaprb ; PD2 (Strobe) auf HIGH-> Daten werden
and.b #%11111011,ciaaprb ; vom Schieberegister in das Datenreg.
; übernommen. Dann PD2 wieder auf LOW.
wb_end movem.l (sp)+,d2/d3
rts
* SetGAL:
* define type of GAL (GAL16V8, GAL20V8, GAL22V10, GAL20RA10)
* call: SetGAL(type);
*
@SetGAL:
move.l d0,_GALType
rts
* VeditOn:
* switch GALer's voltage converter on (IC9)
* elektor's hardware does not support this, so just skip
* call: VeditOn();
@VeditOn:
cmp.l #HW_ELEKTOR_II,_hw_version
beq.s von_end
move.l #IC1,d1
or.l #%00001,_outIC1 ; Q1 von IC1 auf HIGH => VeditOn
move.l _outIC1,d0
bsr @WriteByte ; IC1 setzen
von_end rts
* VeditOff:
* switch GALer's voltage converter off (IC9)
* elektor's hardware does not support his, so just skip
* call: VeditOff();
@VeditOff:
cmp.l #HW_ELEKTOR_II,_hw_version
beq.s voff_end
move.l #IC1,d1
and.l #%11111110,_outIC1 ; Q1 von IC1 auf LOW => VeditOff
move.l _outIC1,d0
bsr @WriteByte ; IC1 setzen
voff_end
rts
* EnableVEdit:
* switch edit voltage to pin 2 or pin 4 of the textool socket
* (pin depends on selected type of GAL)
* call: EnableVEdit();
@EnableVEdit:
cmp.l #HW_ELEKTOR_II,_hw_version ; which hardware is connected?
bne.s ev_galer_hw
;*** elektor hardware ***
cmp.l #GAL16V8,_GALType ; 16V8 selected?
bne.s ev_c1
move.l _outIC4,d0
and.l #%11101111,d0
moveq #IC4,d1
bsr @WriteByte ; set GAL16V8
bra.s ev_c2
ev_c1 ; 20V8, 22V10, 20RA10 selected
move.l _outIC4,d0
or.l #%00010000,d0
moveq #IC4,d1
bsr @WriteByte ; set GAL20V8 etc.
ev_c2
move.l _outIC4,d0
or.l #%00100000,d0
moveq #IC4,d1
bsr @WriteByte ; enable edit voltage (IC3a)
bra.s ev_end
ev_galer_hw ; *** GALer hardware ***
moveq #IC1,d1 ; IC1 einstellen
cmp.l #GAL16V8,_GALType ; 16V8 eingestellt?
bne.s eve_1 ; nein, dann 20V8, 22V10, 20RA10
;*** GAL16V8 ***
moveq #%00000100,d0 ; Q3 von IC1 auf HIGH
bra.s eve_2
;*** 20V8, 22V10, 20RA10 ***
eve_1 moveq #%00000010,d0 ; Q2 von IC1 auf HIGH
eve_2 or.l d0,_outIC1
move.l _outIC1,d0
bsr @WriteByte
ev_end rts
* DisableVEdit:
* remove edit voltage at pin 2 od pin 4
* (pin depends on selected type of GAL)
* call: DisableVEdit();
@DisableVEdit:
cmp.l #HW_ELEKTOR_II,_hw_version
bne.s dv_galer_hw
;*** elektor hardware ***
move.l _outIC4,d0
and.l #%11011111,d0
moveq #IC4,d1
bsr @WriteByte ; disable edit voltage (IC3a)
bra.s dv_end
dv_galer_hw: ;*** GALer hardware ***
moveq #IC1,d1 ; IC1 einstellen
cmp.l #GAL16V8,_GALType ; 16V8 eingestellt?
bne.s dve_1 ; nein, dann wird 20V8 angenommen!
;*** GAL16V8 ***
move.l #%11111011,d0 ; Q3 von IC1 auf LOW
bra.s dve_2
;*** 20V8, 22V10, 20RA10 ***
dve_1 move.l #%11111101,d0 ; Q2 von IC1 auf low
dve_2 and.l d0,_outIC1
move.l _outIC1,d0
bsr @WriteByte
dv_end rts
* LED:
* switch LED on/off
* ON: LED on
* OFF: LED off
* call: LED(ON/OFF);
@LED:
cmp.l #HW_ELEKTOR_II,_hw_version
bne.s led_galer_hw
;*** elektor hardware ***
cmp.l #ON,d0
bne.s led_4
or.l #%00000001,_outIC4
bra.s led_3
led_4 and.l #%11111110,_outIC4
led_3 move.l _outIC4,d0
moveq #IC4,d1
bsr @WriteByte
bra.s led_end
;*** GALer hardware ***
led_galer_hw
cmp.l #ON,d0
bne.s led_2
or.l #%01000000,_outIC1
bra.s led_1
led_2 and.l #%10111111,_outIC1
led_1 move.l #IC1,d1
move.l _outIC1,d0
bsr @WriteByte ; IC1 setzen
led_end rts
* EnableVcc:
* switch on voltage supply of GAL
* GAL16V8: pin 22 of the textool socket
* GAL20V8, 20RA10, 22V10: pin 24 of the textool socket
* call: EnableVcc();
@EnableVcc:
movem.l d0-d7/a0-a6,-(sp) ; Register retten
move.l #300000,d0 ; 300 ms warten
jsr @WaitForTimer
movem.l (sp)+,d0-d7/a0-a6
cmp.l #HW_ELEKTOR_II,_hw_version
bne.s evc_galer_hw
; *** elektor hardware ***
move.l _outIC4,d0
cmp.l #GAL16V8,_GALType ; set voltage according to gal type
bne.s evc_3
and.l #%11101111,d0
bra.s evc_4
evc_3 or.l #%00010000,d0
evc_4 moveq #IC4,d1
bsr @WriteByte ; seletct pin (22 or 24)
move.l _outIC4,d0
or.l #%00000001,d0
moveq #IC4,d1
bsr @WriteByte ; switch on voltage supply (IC3b)
bra.s evc_end
evc_galer_hw: ; *** GALer hardware ***
move.l #IC1,d1 ; IC1 selektieren
cmp.l #GAL16V8,_GALType ; 16V8 eingestellt?
bne.s evc_1 ; nein, dann wird 20V8 angenommen!!!
moveq #%00011000,d0 ; Q4,5 von IC1 auf HIGH=>+5V an Pin22
bra.s evc_2
evc_1 moveq #%00010000,d0 ; Q5 auf HIGH => +5V an Pin 24
evc_2 or.l d0,_outIC1
move.l _outIC1,d0
bsr @WriteByte ; IC1 setzen
evc_end rts
* DisableVcc:
* switch off voltage supply of GAL
* call: DisableVcc();
@DisableVcc:
movem.l d0-d7/a0-a6,-(sp) ; Register retten
move.l #50000,d0 ; sicherheitshalber 50mS warten, bis
jsr @WaitForTimer ; das GAL die letzte Aktion richtig
movem.l (sp)+,d0-d7/a0-a6
cmp.l #HW_ELEKTOR_II,_hw_version
bne.s dvc_galer_hw
; *** elektor hardware ***
move.l _outIC4,d0
and.l #11111110,d0
moveq #IC4,d1
bsr @WriteByte
bra.s dvc_end
dvc_galer_hw ; *** GALer hardware ***
move.l #IC1,d1 ; IC1 selektieren
cmp.l #GAL16V8,_GALType ; 16V8 eingestellt?
bne.s dvc_1 ; nein, dann wird 20V8 angenommen!!!
move.l #%11100111,d0 ; Q4,5 von IC1 auf LOW
bra.s dvc_2
dvc_1 move.l #%11101111,d0 ; Q5 auf HIGH
dvc_2 and.l d0,_outIC1
move.l _outIC1,d0
bsr @WriteByte ; IC1 setzen
dvc_end rts
* EnableOutput:
* switch Output-Enable inputs (OE) of IC3, IC4, IC5 HIGH
* elektor hardware does not support this, so skip it
* call: EnableOutput();
@EnableOutput:
cmp.l #HW_ELEKTOR_II,_hw_version
beq.s eo_end
move.l #IC1,d1
or.l #%00100000,_outIC1
move.l _outIC1,d0
bsr @WriteByte
eo_end rts
* DisableOutput:
* switch Output-Enable inputs (OE) of IC3, IC4, IC5 HIGH
* elektor hardware does not support this, so skip it
* call: EnableOutput();
@DisableOutput:
cmp.l #HW_ELEKTOR_II,_hw_version
beq.s do_end
move.l #IC1,d1
and.l #%11011111,_outIC1
move.l _outIC1,d0
bsr @WriteByte
do_end rts
* ReadByte:
* read bit from IC6a, IC6c or byte from IC7
* call: byte=ReadByte(source);
* source: IC6a, IC6b, IC7
* PD3 is already HIGH, so reading is possible
* elektor's hardware does not support the testing of GALs, so skip it
@ReadByte:
cmp.l #HW_ELEKTOR_II,_hw_version
beq rb_end
and.b #%11111100,ciaaprb ; set PD0 and PD1 LOW
cmp.l #HW_GALER_1_3,_hw_version
beq rb_version1_3 ; hardware version 1.3
; *** this is for the hardware versions 1.0, 1.1, 1.2 ***
cmp.l #IC6a,d0 ; read from IC6a?
bne.s rb_IC7 ; no, then IC7
or.b #%00000001,ciaaprb ; PD0 HIGH=>HIGH at Clk of IC7
; set PD0 HIGH =>IC6a is selected
bsr @PollDelay
moveq #0,d0
move.b ciabpra,d0
not.b d0 ; invert
and.b #%00000001,d0 ; get BUSY bit
bra rb_end ; now we have the state of pin 22
rb_IC7
moveq #0,d0 ; PD3 is HIGH=>reading is possible
or.b #%00000100,ciaaprb ; set PD2 (Strobe) HIGH => put data
and.b #%11111011,ciaaprb ; from input register into shift register
; then set PD2 LOW again
; PD3 is HIGH => reading is possible
move.l d2,-(sp)
moveq #7,d2 ; loop counter
rb_l1 rol.b #1,d0
bsr @PollDelay
move.b ciabpra,d1 ; get BUSY bit
and.b #%00000001,d1 ; AND BUSY bit
or.b d1,d0 ; move BUSY bit in D0
and.b #%11111100,ciaaprb ; set PD0 LOW => LOW at Clk of IC7
or.b #%00000001,ciaaprb ; set PD0 HIGH => HIGH at Clk of IC7
; ==> next bit is available
nop
nop
and.b #%11111100,ciaaprb ; set PD0 LOW=>IC6b is selected
dbf d2,rb_l1 ; read 8 bits
not.b d0 ; invert them
move.l (sp)+,d2
bra rb_end
; *** this is for hardware version 1.3 ***
rb_version1_3:
cmp.l #IC6a,d0 ; read from IC6a?
bne.s rb_c1
; read IC6a
; PD0 and PD1 is LOW=>IC6a is selected
bsr @PollDelay
moveq #0,d0
move.b ciabpra,d0 ; read parallel port
not.b d0 ; invert
and.b #%00000001,d0 ; get BUSY bit
bra.s rb_end ; now we have the state of pin 22
rb_c1 cmp.l #IC6c,d0 ; read from IC6b?
bne.s rb_c2 ; no, then IC7
; Read IC6c
or.b #%00000010,ciaaprb ; PD0 LOW, PD1 HIGH => IC6c is selected
moveq #0,d0
bsr @PollDelay
move.b ciabpra,d0 ; read parallel port
not.b d0 ; invert
and.b #%00000001,d0 ; get BUSY bit
bra.s rb_end ; now we have the state of pin 23
rb_c2 ; read IC7
moveq #0,d0 ; PD3 is HIGH=>reading is possible
or.b #%00000101,ciaaprb ; set PD2 (Strobe) HIGH => put data
and.b #%11111011,ciaaprb ; from input register into shift register
; then set PD2 LOW again
; PD3 is HIGH => reading is possible
move.l d2,-(sp)
moveq #7,d2 ; loop counter
rb_l2 rol.b #1,d0
bsr @PollDelay
move.b ciabpra,d1 ; get BUSY bit
and.b #%00000001,d1 ; AND BUSY bit
or.b d1,d0 ; move BUSY bit in D0
and.b #%11111100,ciaaprb ; set PD0 LOW => LOW at Clk of IC7
or.b #%00000001,ciaaprb ; set PD0 HIGH => HIGH at Clk of IC7
; ==> next bit is available
dbf d2,rb_l2 ; read 8 bits
not.b d0 ; invert them
move.l (sp)+,d2
rb_end
rts ; D0 is result
* SetRow:
* set address to RAG0-RAG5
* call: SetRow(row);
* row: row which should be selected (0-63)
@SetRow:
move.l d0,-(sp) ; Row (D0) auf Stack
cmp.l #GAL22V10,_GALType
beq setrow22V10
cmp.l #GAL20RA10,_GALType
beq setrow20RA10
cmp.l #HW_ELEKTOR_II,_hw_version
bne sr_galer_hw
; *** elektor hardware ***
; RAG4 and RAG5 are equal for both,
; GAL16V8 and GAL20V8
and.l #%10111110,_outIC1 ; clear RAG4 and RAG5
and.l #%00100000,d0
asl.b #1,d0 ; get RAG5
or.l d0,_outIC1 ; set RAG5
move.l (sp),d0
and.l #%00010000,d0
asr.b #4,d0 ; get RAG4
or.l d0,_outIC1 ; set RAG4
cmp.l #GAL16V8,_GALType
bne.s sr_20V8
; *** GAL16V8 ***
move.l (sp),d0
and.l #%00000001,d0 ; get RAG0
asl.b #2,d0
and.l #%11111011,_outIC1
or.l d0,_outIC1 ; set RAG0
move.l (sp),d0
and.l #%00000110,d0 ; get RAG1 and RAG2
and.l #%11111001,_outIC4
or.l d0,_outIC4 ; set RAG1 and RAG2
move.l (sp),d0
and.l #%00001000,d0 ; get RAG3
asl.b #2,d0
and.l #%11011111,_outIC1
or.l d0,_outIC1 ; set RAG3
bra.s sr_write
sr_20V8 ; *** GAL20V8 ***
move.l (sp),d0
and.l #%00000001,d0 ; get RAG0
asl.b #4,d0
and.l #%11101111,_outIC1
or.l d0,_outIC1 ; set RAG0
move.l (sp),d0
and.l #%00000110,d0 ; get RAG1 and RAG2
asl.b #5,d0
and.l #%00111111,_outIC4
or.l d0,_outIC4 ; set RAG1 and RAG2
move.l (sp),d0
and.l #%00001000,d0 ; get RAG3
asr.b #2,d0
and.l #%11111101,_outIC4
or.l d0,_outIC4 ; set RAG3
sr_write ; write bytes to ICs
move.l #IC1,d1
move.l _outIC1,d0
bsr @WriteByte
bra setrowend
sr_galer_hw ; *** GALer hardware ***
; *** GAL16V8 und GAL20V8 ***
; RAG5 setzen (bei 16 und 20V8 gleich)
and.l #$fe,_outIC5 ; Bit0(=RAG5) löschen
asr.b #5,d0 ; Bit0 von D0=RAG5
or.l d0,_outIC5 ; RAG5=Bit von D0=> RAG5 gesetzt
cmp.l #GAL16V8,_GALType ; GAL16V8?
bne.s setrow20V8 ; nein, dann GAL20V8 annehmen
;*** GAL16V8 ***
; RAG0 setzen
move.l (sp),d0 ; row holen
and.l #$ef,_outIC3 ; Bit4(=RAG0) löschen
and.l #1,d0 ; Bit0 von "row" ausmaskieren
asl.b #4,d0
or.l d0,_outIC3 ; Bit4(=RAG0) setzen
; RAG1-RAG4 setzen
move.l (sp),d0 ; row holen
and.l #$0f,_outIC4 ; Bit4-7(=RAG1-RAG4) löschen
and.l #%00011110,d0 ; Bit1-4 von "row" ausmaskieren
asl.l #3,d0 ; an Bit4-7 schieben
or.l d0,_outIC4 ; RAG1-RAG4 setzen
bra.s write
;*** GAL20V8 ***
setrow20V8 ; RAG0 für GAL20V8 setzen
move.l (sp),d0 ; row holen
and.l #%11011111,_outIC3 ; Bit5(=RAG0) löschen
and.l #1,d0 ; Bit0 von "row" ausmaskieren
asl.b #5,d0
or.l d0,_outIC3 ; Bit5(=RAG0) setzen
; RAG4 setzen
move.l (sp),d0 ; row holen
and.l #%01111111,_outIC4 ; Bit7(=RAG4) löschen
and.l #%00010000,d0 ; Bit4 von "row" ausmaskieren
asl.l #3,d0
or.l d0,_outIC4 ; Bit7(=RAG4) setzen
; RAG1-RAG3 setzen
move.l (sp),d0 ; row holen
and.l #%11100011,_outIC4 ; Bit2-4(=RAG1-RAG3) löschen
and.l #%00001110,d0 ; Bit1-3 aus "row" ausmaskieren
asl.l #1,d0
or.l d0,_outIC4 ; RAG1-RAG3 setzen
write ; errechnete Werte in ICs schreiben
move.l #IC3,d1
move.l _outIC3,d0
bsr @WriteByte
move.l #IC4,d1
move.l _outIC4,d0
bsr @WriteByte
move.l #IC5,d1
move.l _outIC5,d0
bsr @WriteByte
bra.s setrowend
; *** GAL22V10 und GAL20RA10 ***
setrow22V10 ; bei 22V10 und 20RA10 GALs wird RAG0-5 in
setrow20RA10 ; das interne Schiebereg. des GALs getaktet,
; da diese GALs keine RAG-Pins haben
moveq #5,d1 ; D0 = Row
setrow1
movem.l d0/d1,-(sp)
and.l #%0000001,d0 ; LSB ausmaskieren
bsr.s @SDIn ; RAGx ins Schieberegister des
bsr @Clock ; GALs takten
movem.l (sp)+,d0/d1
asr.b #1,d0
dbf d1,setrow1
setrowend
addq.l #4,sp ; Stack korrigieren
rts
* SDIn:
* set bit at SDIn input of the GAL (pin 11 of the textool socket)
* call: SDIn(bit); bit: 0=LOW; 1=HIGH
@SDIn:
cmp.l #HW_ELEKTOR_II,_hw_version
bne.s sd_galer_hw
; *** elektor hardware ***
asl.b #7,d0 ; shift bit #0 to bit #7
and.l #%01111111,_outIC1 ; clear bit #7 of IC1
or.l d0,_outIC1
move.l _outIC1,d0
move.l #IC1,d1
bsr @WriteByte ; set SDIn
bra.s sd_end
sd_galer_hw ; *** GALer hardware ***
; Bit steht in d0
asl.b #2,d0 ; an die richtige Stelle schieben
and.l #%11111011,_outIC5 ; SDIn-Bit löschen
or.l d0,_outIC5 ; Bit auf LOW oder HIGH setzen
move.l #IC5,d1
move.l _outIC5,d0
bsr @WriteByte
sd_end rts
* SDOut:
* read bit from SDOut (SDOut is an open drain output!)
* pin 14 (GAL16V8, 22V10, 20RA10), pin 15 (GAL20V8) of the textool socket
* call: bit=SDOut();
* bit: 0: SDOut=LOW; 1: SDOut=HIGH
@SDOut:
cmp.l #HW_ELEKTOR_II,_hw_version
bne.s sdo_galer_hw
; *** elektor hardware ***
cmp.l #GAL20V8,_GALType
beq.s sdo_c1
move.l _outIC2,d0
and.b #%11101111,d0 ; select IC2a
move.l #IC2,d1
bsr @WriteByte
nop ; nops are not really necessary
nop
nop
move.b ciabpra,d0 ; get BUSY bit
and.l #%00000001,d0
bra.s sdo_end
sdo_c1 ; GAL20V8
move.l _outIC2,d0
or.b #%00010000,d0 ; select IC2b
move.l #IC2,d1
bsr @WriteByte
nop ; nops are not really necessary
nop
nop
move.b ciabpra,d0 ; get BUSY bit
and.l #%00000001,d0
bra.s sdo_end
sdo_galer_hw ; *** GALer hardware ***
move.l #IC7,d0 ; ein Byte aus IC7 holen
bsr @ReadByte ; Bit0=Pin14, Bit1=Pin15
cmp.l #GAL20V8,_GALType ; GAL20V8 eingestellt?
beq.s sdo_c2 ; nein, dann 16V8, 22V10, 20RA10
and.l #1,d0 ; Bit0 ausmaskieren
bra.s sdo_end ; D0=Bit
; GAL20V8
sdo_c2 asr.l #1,d0 ; SDOut-Bit an Bit-Pos. 0
and.l #1,d0
sdo_end ; 32-Bit-Ergebnis in D0
rts
* PollDelay
* wait about 10us
* This function does polling. I know that this is not a very good methode in
* a multitasking system. But we have to wait just some micro seconds.
* This is not possible when using the timer device or CIA timer interrupts.
* Using this things lasts at least 400us (timer device) or 180us (CIA timer
* interrupts). This is too long. So we have to poll, sorry.
*
* A0 will be changed!
@PollDelay:
move.l _cia_timer_low,a0 ; load timer
move.b #255,(a0)
move.l _cia_timer_high,a0
clr.b (a0)
; start timer
move.l _cia_timer_cr,a0
move.b _cia_timer_start,(a0)
move.l _cia_timer_low,a0
PD_loop:
cmp.b #250,(a0) ; poll timer's low byte
bhi.s PD_loop
; stop timer
move.l _cia_timer_cr,a0
move.b _cia_timer_stop,(a0)
rts
* Clock:
* generate Low-High-Low transition at GAL's clock input (pin 10 of the
* textool socket) - when calling this function SCLK must be Low already
*
* call: Clock();
@Clock:
cmp.l #HW_ELEKTOR_II,_hw_version
bne.s cl_galer_hw
; *** elektor hardwar ***
or.l #%00000010,_outIC1 ; SCLK HIGH
move.l #IC1,d1
move.l _outIC1,d0
bsr @WriteByte
and.l #%111111101,_outIC1 ; SCLK LOW
move.l #IC1,d1
move.l _outIC1,d0
bsr @WriteByte
bra.s cl_end
cl_galer_hw ; *** GALer hardware ***
or.l #%00000010,_outIC5 ; SCLK-Bit auf HIGH
move.l #IC5,d1
move.l _outIC5,d0
bsr @WriteByte
and.l #%11111101,_outIC5 ; SCLK-Bit auf LOW
move.l #IC5,d1
move.l _outIC5,d0
bsr @WriteByte
cl_end rts
* STRImpuls:
* set /STR low (pin 13 of the textool socket) for a duration of "STRLength"
* call: STRImpuls(long STRLength);
* STRLength: duration of the low impulse in microsecondes (32 bit!)
@STRImpuls:
movem.l d0-d7/a0-a6,-(sp) ; Register retten
move.l 4,a6
jsr _LVOForbid(a6) ; forbid task switching
cmp.l #HW_ELEKTOR_II,_hw_version
bne.s sim_galer_hw
; *** elektor hardware **
and.l #%11110111,_outIC1 ; set STR LOW
move.l #IC1,d1
move.l _outIC1,d0
bsr @WriteByte
cmp.l #300,(sp) ; writing a value into the IC needs
bls.s sim_c1 ; about 300us, so it makes no sense
move.l (sp),d0 ; to use the timer if the time to
sub.l #300,d0 ; wait is less than 300us
jsr @WaitForTimer
sim_c1
or.l #%00001000,_outIC1 ; set STR HIGH
move.l #IC1,d1
move.l _outIC1,d0
bsr @WriteByte
bra.s sim_end
sim_galer_hw ; *** GALer hardware ***
and.l #%11110111,_outIC5 ; STR-Pin auf LOW
move.l #IC5,d1
move.l _outIC5,d0
bsr @WriteByte
cmp.l #100,(sp) ; bis ein Wert in ein IC getaktet wird
bls.s sim_c2 ; vergehen ca. 100us => keinen Timer
move.l (sp),d0 ; Dauer des Impulses in Mikrosekunden
jsr @WaitForTimer ; Low-Impuls
sim_c2
or.l #%00001000,_outIC5 ; STR-Pin wieder auf HIGH
move.l #IC5,d1
move.l _outIC5,d0
bsr @WriteByte
sim_end jsr _LVOPermit(a6) ; permit task switching
movem.l (sp)+,d0-d7/a0-a6 ; Registerinhalte zurückholen
rts
* SetPV:
* set P/V pin
* call: SetPV(mode);
* mode : VERIFY (read, P/V low), PROG (write, P/V high)
@SetPV:
; mode = D0
cmp.l #HW_ELEKTOR_II,_hw_version
bne.s spv_galer_hw
; *** elektor hardware ***
cmp.l #GAL16V8,_GALType
bne.s spv_c1
; *** GAL16V8 ***
move.l _outIC1,d1
and.l #%11101111,d1 ; clear P/V
asl.b #4,d0
or.l d0,d1 ; set P/V according to mode
move.l d1,d0
move.l #IC1,d1
bsr @WriteByte
bra spv_end
spv_c1
cmp.l #GAL20V8,_GALType
bne.s spv_c2 ; *** GAL20V8 ***
move.l _outIC4,d1
and.l #%11110111,d1 ; clear P/V
asl.b #3,d0
or.l d0,d1 ; set P/V according to mode
move.l d1,d0
move.l #IC4,d1
bsr @WriteByte
bra.s spv_end
spv_c2 ;*** 22V10, 20RA10 ***
move.l _outIC4,d1
and.l #%10111111,d1 ; clear P/V
asl.b #6,d0
or.l d0,d1 ; set P/V according to mode
move.l d1,d0
move.l #IC4,d1
bsr @WriteByte
bra.s spv_end
spv_galer_hw ; *** GALer hardware ***
cmp.l #GAL16V8,_GALType ; GAL16V8?
bne.s spv_c3 ; nein, dann 1
;*** GAL16V8 ***
move.l _outIC3,d1
and.l #%11011111,d1
asl.b #5,d0 ; Mode-Bit zu Bit 5 schieben
or.l d0,d1
move.l d1,d0 ; P/V setzen
move.l #IC3,d1 ; IC3 setzen
bsr @WriteByte
bra.s spv_end
spv_c3
cmp.l #GAL20V8,_GALType
bne.s spv_c4
;*** GAL20V8 ***
move.l _outIC3,d1
and.l #%10111111,d1
asl.b #6,d0 ; Mode-Bit zu Bit 6 schieben
or.l d0,d1
move.l d1,d0 ; P,/V-Bit setzen
move.l #IC3,d1 ; IC3 setzen
bsr @WriteByte
bra.s spv_end
spv_c4
;*** 22V10, 20RA10 ***
move.l _outIC4,d1
and.l #%11111011,d1
asl.b #2,d0
or.l d0,d1
move.l d1,d0 ; P,/V-Bit setzen
move.l #IC4,d1 ; IC4 setzen
bsr @WriteByte
spv_end
rts
* Edit-Mode:
* switch GAL into edit mode: /STR = HIGH, P/V = LOW,
* SDOUT(open drain output!) = VIH, all VIL-pins = VIL
* call: EditMode(mode);
* mode: PROG or VERIFY (needed to select voltage)
@EditMode:
movem.l d0-d7/a0-a6,-(sp) ; Register sichern
cmp.l #HW_ELEKTOR_II,_hw_version
bne.s em_galer_hw
; *** elektor hardware ***
cmp.l #GAL16V8,_GALType ; GAL16V8
bne.s em_c7 ; no, then goto em_c7
;*** GAL16V8 ***
moveq #IC4,d1
moveq #%00001000,d0
bsr @WriteByte
moveq #IC1,d1
moveq #%00001000,d0 ; set /STR high
bsr @WriteByte
moveq #IC2,d1
moveq #%00000000,d0 ; set SDOut high and
bsr @WriteByte
bra em_c2 ; select voltage
em_c7 cmp.l #GAL20V8,_GALType
bne.s em_c8 ;*** GAL20V8 ***
moveq #IC4,d1
moveq #%00000000,d0
bsr @WriteByte
moveq #IC1,d1
moveq #%00001000,d0 ; set /STR high
bsr @WriteByte
moveq #IC2,d1
moveq #%00010000,d0 ; set SDOut high and
bsr @WriteByte
bra.s em_c2 ; select voltage
em_c8 ;*** GAL20RA10 ***
;*** GAL22V10 ***
moveq #IC4,d1
moveq #%00000000,d0
bsr @WriteByte
moveq #IC1,d1
moveq #%00001000,d0 ; set /STR high
bsr @WriteByte
moveq #IC2,d1
moveq #%00000000,d0 ; set SDOut high and
bsr @WriteByte
bra.s em_c2 ; select voltage
em_galer_hw ; *** GALer hardware ***
cmp.l #GAL16V8,_GALType ; GAL16V8?
bne.s em_c1 ; nein, dann em_c1
;*** GAL16V8 ***
moveq #IC3,d1 ; IC3, P/V auf LOW
moveq #%00000000,d0
bsr @WriteByte
moveq #IC4,d1
moveq #%00000000,d0 ; IC4 initialisieren
bsr @WriteByte
moveq #IC5,d1 ; /STR auf HIGH
moveq #%00011000,d0 ; IC5 initialisieren
bsr @WriteByte
bra.s em_c2
em_c1 cmp.l #GAL20V8,_GALType
bne.s em_c5
;*** GAL20V8 ***
moveq #IC3,d1 ; IC3, P/V auf LOW
moveq #%00000000,d0
bsr @WriteByte
moveq #IC4,d1
moveq #%00000000,d0 ; IC4 initialisieren
bsr @WriteByte
moveq #IC5,d1 ; /STR auf HIGH
moveq #%00101000,d0 ; IC5 initialisieren
bsr @WriteByte
bra.s em_c2
em_c5
;*** GAL20RA10 ***
;*** GAL22V10 ***
moveq #IC3,d1 ; IC3, OPs auf VIL
moveq #%00000000,d0
bsr @WriteByte
moveq #IC4,d1
moveq #%00000000,d0 ; IC4, P/V auf LOW
bsr @WriteByte
moveq #IC5,d1 ; /STR, SDOUT auf HIGH
moveq #%00011000,d0 ; IC5 initialisieren
bsr @WriteByte
em_c2
; richtige Spannung auswählen
cmp.l #VERIFY,(sp) ; Lesen?
bne.s em_c3 ; nein, dann Programmieren!
moveq #4,d0 ; 12 Volt einstellen
cmp.l #GAL22V10,_GALType ; wenn 22V10, dann 16.5 Volt
bne.s em_c6
moveq #0,d0
em_c6 bsr @SetVolt
bra.s em_c4
em_c3 move.l _prog_volt,d0 ; Programmierspannung einstellen
bsr @SetVolt
em_c4 bsr @VeditOn ; Edit-Spannung aufbauen
move.l #50000,d0 ; 50 ms warten, bis sich die
jsr @WaitForTimer ; Edit-Spannung aufgebaut hat
bsr @EnableOutput ; Bits anlegen
bsr @EnableVcc ; Vcc anlegen
move.l #100000,d0 ; Prellzeit der Relais überbrücken
jsr @WaitForTimer
bsr @EnableVEdit ; Edit-Spannung anlegen
; GAL befindet sich jetzt im Edit-Mode
moveq #5,d0 ; 5 us warten bevor nächste Aktion
jsr @WaitForTimer ; erlaubt ist
movem.l (sp)+,d0-d7/a0-a6 ; Registerinhalte zurückholen
rts
* ExitEditMode:
* Schaltet zuerst VEdit und VCC ab, dann wird der Inhalt der ICs
* zurückgesetzt.
* Aufruf: ExitEditMode();
@ExitEditMode:
movem.l d0-d7/a0-a6,-(sp) ; Register sichern
bsr @DisableVEdit
bsr @DisableVcc
bsr @InitHardware
bsr @EnableOutput
movem.l (sp)+,d0-d7/a0-a6
rts
* SetVolt:
* set voltage
* GALer: select voltage by use of IC 10 and IC 11
* elektor: set bits of AD converter
* call: SetVolt(value);
* value: 0=16.50 Volt; 1=15.75 Volt; 2=14.5 Volt; 3=14.00 Volt; 4=12.00 Volt
*
@SetVolt:
; Parameter in D0
move.l d0,-(sp) ; Wert sichern
cmp.l #HW_ELEKTOR_II,_hw_version
bne.s sv_galer_hw
; *** elektor hardware ***
move.l _outIC2,d1 ; clear all bits of IC 2 which
and.l #%00110000,d1 ; belongs to the DA converter
tst d0 ; 16.5 V
bne.s sv_c1
or.l #%01000100,d1
bra.s sv_c5
sv_c1 cmp #1,d0 ; 15.75 V
bne.s sv_c2
or.l #%10001111,d1
bra.s sv_c5
sv_c2 cmp #2,d0 ; 14.5 V
bne.s sv_c3
or.l #%10000101,d1
bra.s sv_c5
sv_c3 cmp #3,d0 ; 14.0 V
bne.s sv_c4
or.l #%10000001,d1
bra.s sv_c5
sv_c4 ; 12.0 V
or.l #%10000000,d1
sv_c5 move.l d1,d0 ; write value into d0
moveq #IC2,d1 ; write IC number into d1
bsr @WriteByte ; set voltage
bra.s sv_end
sv_galer_hw ; *** GALer hardware ***
and.l #%00000001,d0
rol.l #7,d0
and.l #%01111111,_outIC1
or.l d0,_outIC1 ; Q8 (Pin 11) von IC1 setzen
move.l _outIC1,d0
move.l #IC1,d1
bsr @WriteByte
move.l (sp),d0
and.l #%00000110,d0
rol.l #5,d0
and.l #%00111111,_outIC5
or.l d0,_outIC5 ; Q7 und Q8 von IC5 setzen
move.l _outIC5,d0
move.l #IC5,d1
bsr @WriteByte
sv_end addq.l #4,sp
rts
*** The following routines are only for the 22V10 and/or 20RA10 GALs. ***
* SetPESSAVE:
* set PESSAVE pin (pin 4) of the GAL20RA10
* remark: this is routine is used for GAL22V10 only
* call: SetPESSAVE(pegel)
* parameter: pegel = HIGH or LOW
* SetERASE:
* set ERASE pin (pin 4) of the GAL22V10
* remark: this is routine is used for GAL22V10 only
* call: SetERASE(pegel)
* parameter: pegel = HIGH or LOW
@SetPESSAVE:
@SetERASE:
cmp.l #HW_ELEKTOR_II,_hw_version
bne.s ser_galer_hw
; *** elektor hardware ***
and.l #%01111111,_outIC4
cmp.l #LOW,d0
beq.s ser_c1
or.l #%10000000,_outIC4
bra.s ser_c1
ser_galer_hw ; *** GALer hardware ***
and.l #%11110111,_outIC4
cmp.l #LOW,d0
beq.s ser_c1
or.l #%00001000,_outIC4
ser_c1 move.l #IC4,d1
move.l _outIC4,d0
bsr @WriteByte
rts
* SetCLR:
* set CLR pin (pin 6) of GAL22V10 and GAL20RA10
* call: SetCLR(pegel)
* parameter: pegel = HIGH or LOW
@SetCLR:
cmp.l #HW_ELEKTOR_II,_hw_version
bne.s sclr_galer_hw
; *** elektor hardware ***
and.l #%11111011,_outIC4
cmp.l #LOW,d0
beq.s sclr_c1
or.l #%00000100,_outIC4
bra.s sclr_c1
sclr_galer_hw ; *** GALer hardware ***
and.l #%11011111,_outIC4
cmp.l #LOW,d0
beq.s sclr_c1
or.l #%00100000,_outIC4
sclr_c1 move.l #IC4,d1
move.l _outIC4,d0
bsr @WriteByte
rts
* SetBE:
* set BE pin (pin 7) of GAL22V10 and GAL20RA10
* call: SetBE(pegel)
* parameter: pegel = HIGH or LOW
@SetBE:
cmp.l #HW_ELEKTOR_II,_hw_version
bne.s sbe_galer_hw
; *** elektor hardware ***
and.l #%11011111,_outIC1
cmp.l #LOW,d0
beq.s sbe_c1
or.l #%00100000,_outIC1
sbe_c1 move.l #IC1,d1
move.l _outIC1,d0
bsr @WriteByte
bra.s sbe_end
sbe_galer_hw ; *** GALer hardware ***
and.l #%10111111,_outIC4
cmp.l #LOW,d0
beq.s sbe_c2
or.l #%01000000,_outIC4
sbe_c2 move.l #IC4,d1
move.l _outIC4,d0
bsr @WriteByte
sbe_end rts
* SetARCH:
* set ARCH pin (pin 8) of GAL22V10 and GAL20RA10
* call: SetARCH(pegel)
* parameter: pegel = HIGH or LOW
@SetARCH:
cmp.l #HW_ELEKTOR_II,_hw_version
bne.s sar_galer_hw
; *** elektor hardware ***
and.l #%11111110,_outIC1
cmp.l #LOW,d0
beq.s sar_c1
or.l #%00000001,_outIC1
sar_c1 move.l #IC1,d1
move.l _outIC1,d0
bsr @WriteByte
bra.s sar_end
sar_galer_hw ; *** GALer hardware ***
and.l #%01111111,_outIC4
cmp.l #LOW,d0
beq.s sar_c2
or.l #%10000000,_outIC4
sar_c2 move.l #IC4,d1
move.l _outIC4,d0
bsr @WriteByte
sar_end rts
* SetANDBE:
* set ANDBE pin (pin 9) of GAL20RA10
* remark: this routine is for the 22V10 GAL only
* call: SetCLR(pegel)
* parameter: pegel = HIGH or LOW
@SetANDBE:
cmp.l #HW_ELEKTOR_II,_hw_version
bne.s sand_galer_hw
; *** elektor hardware ***
and.l #%10111111,_outIC1
cmp.l #LOW,d0
beq.s sand_c1
or.l #%01000000,_outIC1
sand_c1 move.l #IC1,d1
move.l _outIC1,d0
bsr @WriteByte
bra.s sand_end
sand_galer_hw ; *** GALer hardware ***
and.l #%11111110,_outIC5
cmp.l #LOW,d0
beq.s sand_c2
or.l #%00000001,_outIC5
sand_c2 move.l #IC5,d1
move.l _outIC5,d0
bsr @WriteByte
sand_end
rts
SECTION data,DATA
_cia_timer_low: dc.l 0 ; address of TxLO
_cia_timer_high: dc.l 0 ; address of TxHI
_cia_timer_cr: dc.l 0 ; address of CRx
_cia_timer_start: dc.b 0 ; value to start cia timer
_cia_timer_stop: dc.b 0 ; value to stop cia timer
_hw_version: dc.l 0
cia_addrb: dc.b 0
cia_bddra: dc.b 0
END